FUNCTION New class browsers for Smalltalk. Features of FullBrowser without the clutter.
ST-VERSIONS Objectworks 4.1, Visualworks 1.0
PREREQUISITES None
CONFLICTS None
DISTRIBUTION world
VERSION 4.1.1
DATE June 28, 1993
SUMMARY ClassBrowser & SystemOrganizerBrowser
Instances of SystemOrganizerBrowser browse a SystemOrganizer like ''Smalltalk organization''. This class and its collaborator (ClassBrowser) provide a replacement for the standard Browser for browsing classes in Smalltalk.
Instances of ClassBrowser support browsing and editing of individual classes providing (in concert with its collaborator SystemOrganizerBrowser) significantly more abilitity than the standard Browser/BrowserView.
To open a SystemOrganizerBrowser of this evaluate (SystemOrganizerBrowser open).
Carl Gable Watts
"!
Browser subclass: #SystemOrganizerBrowser
instanceVariableNames: 'takenClass '
classVariableNames: ''
poolDictionaries: ''
category: 'Tools-Programming'!
SystemOrganizerBrowser comment:
'Instances of SystemOrganizerBrowser browse a SystemOrganizer like ''Smalltalk organization''. This class and its collaborator (ClassBrowser) provide a replacement for the standard Browser for browsing classes in Smalltalk.
This class was written and is owned by Carl Watts (Email: Carl@ParcPlace.com). You are free to use this class and modify it if you wish but you cannot redistribute this class or any part of it without including this paragraph in the class comment. Please send any improvements you implement to me (at my email address) so I can consider putting them in my next version.
This class and its collaborating class ClassBrowser both have install messages that you can use to modify the Browser class so it will use these new browsers in preference to the standard ones in Browser. There are also uninstall messages.
The menus used by this class are more context sensitive than many other Smalltalk applications. The menues are constructed to be sensitive to whatever you have selected. The menu items are very different if you have something selected and if you don''t (as context sensitively appropriate). Methods for all menu selections are in the ''category menu methods'' and ''class menu methods'' protocols. The comment for each will explain its use.
To open an instance of this evaluate (SystemOrganizerBrowser open).
Instance Variables:
takenClass <Symbol> The name of the last ''taken'' class by the ''take it'' menu item.
self makeClassNamed: newClassName first asSymbol superClass: Object!
makeNewSubclass
"Prompt for the name of a new subclass for the currently selected class. If the name entered is not already the name of a class, then make it a class in the current category."
| aString newClassName |
self changeRequest ifFalse: [^self].
aString := self prompt: 'Enter name of new subclass' initially: ''.
self makeClassNamed: newClassName first asSymbol superClass: self nonMetaClass!
printoutClass
"Printout the selected class with all of its methods to a printer."
"Use the inherited printOutClass."
super printOutClass!
showCollaborators
"Show the collaborating classes of the selected class."
DialogView warn: 'Show collaborators has not been implemented yet.'!
showLeiges
"Show the leige (sp?) classes of the selected class. These are classes which use the selected class but which the selected class don't use."
DialogView warn: 'Show leiges has not been implemented yet.'!
showMinions
"Show the minion classes of the selected class. These are classes which the selected class uses but which don't use it."
DialogView warn: 'Show minions has not been implemented yet.'!
takeClass
"Take the currently selected class class and remember it. This allows it to be moved into a different class category (see andMoveClassInHere) or moved to a different superclass (see andMakeItASubclass). To move it to a different class category, select the category you want to move it to and perform: andMoveClassInHere from the menu for the category list. To move it to be a subclass of a different superclass, select the new superclass and perform: andMakeItASubclass from the menu for the class list."
takenClass := self className! !
!SystemOrganizerBrowser methodsFor: 'category menu methods'!
andMoveClassInHere
"Move the last 'taken' class (see takeClass) into the currently selected class category."
"Answer a menu appropriate for the given collection of message selectors and with objectOfVerbs (a String) implied in the menu labels. If objectOfVerbs is nil then the labels will be generated without a objectOfVerbs."
"This behavior should exist in PopUpMenu. And PopUpMenu should be generalized since a menu is a more general concept than a PopUpMenu."
"This functionality is currently being implemented by class ClassBrowser."
"Make a new Class named aClassname with aClass as its superclass. Put the new class in the currently selected class category. If such a class already exists, then just show the existing one."
| newClassName |
newClassName := aClassname asString copy.
newClassName at: 1 put: newClassName first asUppercase.
"Uninstall the method in Browser to have SystemOrganizerBrowser replace the normal Browser."
Browser class
compile: 'open
"Browser open"
self openOn: Smalltalk organization'
classified: 'view creation'! !
!SystemOrganizerBrowser class methodsFor: 'class initialization'!
install
"Install methods in Browser to have ClassBrowser and SystemOrganizerBrowser replace the normal Browsers."
ClassBrowser doInstall.
self doInstall!
unInstall
"Uninstall the methods in Browser to have ClassBrowser and SystemOrganizerBrowser replace the normal Browsers."
ClassBrowser doUninstall.
self doUninstall! !
Browser subclass: #ClassBrowser
instanceVariableNames: 'variable upToObject '
classVariableNames: 'TakenMethod '
poolDictionaries: ''
category: 'Tools-Programming'!
ClassBrowser comment:
'Instances of ClassBrowser support browsing and editing of individual classes providing (in concert with its collaborator SystemOrganizerBrowser) significantly more abilitity than the standard Browser/BrowserView.
This class was written and is owned by Carl Watts (Email: Carl@ParcPlace.com). You are free to use this class and modify it if you wish but you cannot redistribute this class or any part of it without including this paragraph in the class comment. Please send any improvements you implement to me (at my email address) so I can consider putting them in my next version.
This class and its collaborating class ClassBrowser both have install messages that you can use to modify the Browser class so it will use these new browsers in preference to the standard ones in Browser. There are also uninstall messages.
The most important feature of this browser is that it always shows you inherited attributes as well as attributes locally defined in the class. Attributes (like representation variables and methods) that are locally defined are shown highlighted in bold.
The metaphor for moving something (like a method) to a different place (like a different protocol) is to select the item you want to move, select ''take it...'' from the menu, select the place you want to move it to (like the protocol, and then select ''and move it here...'' from the menu of destination.
To try out using a class browser, open a SystemOrganizerBrowser (SystemOrganizerBrowser open), and then browse a class. You can install these browsers so that they will be used in preference to Browser by evaluating ''ClassBrowser install''. They can later be uninstalled by evaluating ''ClassBrowser uninstall''.
The PopUpMenus used by this class are more context sensitive than many other Smalltalk applications. The menues are constructed to be sensitive to whatever you have selected. The menu items are very different if you have something selected and if you don''t (as context sensitively appropriate). The methods associated with the items in the variable list menu are in the ''variable menu methods'' protocol. Likewise for the protocol list and the selector list. The comments for these methods will explain their purpose.
Instance of this class support an interface that allows manipulation of the representation as easily as the behavior. A ListView shows the instance variables (when viewing the instance methods) or the class variables (when viewing the class methods).
Future work:
- finish all unimplemented menu items.
- allow manipulation of class instance variables and pool variables in the variables list.
- allow ''and copy it here...'' of methods between classes.
- add ''Inherited'' check button
- replace sequential prompters with a single dialog
Instance Variables:
variable <Symbol> The currently selected variable (instance variable or class variable).
upToObject <Boolean> Indicates whether to show protocols and methods inherited from Object.
Class Variables:
TakenMethod <Array> The class and the message selector that was last ''taken'' by the ''take it'' menu item.
'!
!ClassBrowser methodsFor: 'protocol list'!
allProtocolList
"Answer the sequenceable collection containing the message categories for the class."
"Currently they are sorted in alphabetical order. An improvement would be eldest ancestor priority order."
"Browse all methods that call the currently selected method by sending the message to 'self' or 'super'. All such methods will be in one of the superclasses or in one of the subclasses."
"I can't determine fast enough yet whether the message selector is REALLY being sent to 'self' or 'super' so instead I will browse any method that sends the message selector and COULD be sending it to 'self' or 'super' to invoke the method in question. I am still considering whether it is useful to weed out methods that couldn't invoke the method directly (even via super) because of intervening over-riders."
"Evaluate aBlock will all the classes upto Object (inclusive of Object if that flag is set) and with the collection of message selectors from that class that are in the selected protocol and are responders to messages to the selectedClass."
"Answer a menu appropriate for the given collection of message selectors and with objectOfVerbs (a String) implied in the menu labels. If objectOfVerbs is nil then the labels will be generated without a objectOfVerbs."
"The objectOfVerbs will be replaced by 'it' in the labels."
"This behavior should exist in PopUpMenu. And PopUpMenu should be generalized since a menu is a more general concept than a PopUpMenu."
^self class menuForSelectorPredicates: selectorPredicates objectOfVerbs: objectOfVerbs! !
!ClassBrowser methodsFor: 'selector list support'!
availableSelectorsWhich: aBlock
"Answer the set containing the message selectors that the current class defines (upto object if that flag is set)."
"File out the currently selected protocol on the specified fileName. Prompt the user for the file name and whether or not to include inherited methods."
| fileStream includeInherited |
includeInherited := DialogView confirm: 'Include any inherited methods?'.
fileStream := SourceCodeStream on: fileName asFilename writeStream.
"Find a method that matches aString and show it. Answer true if a matching method was found. False in not. nil if matches were found but none were satisfactory to the user."
"Answer a collection of labels appropriate for the given collection of selectorPredicates (menu selectors that are predicate phrases) and with objectOfVerbs implied in the labels. If objectOfVerbs is nil then the labels will be generated without a objectOfVerbs."
"The objectOfVerbs will be replaced by 'it' in the labels."
"This functionality should all be implemented in PopUpMenu or something like that."
| labels selectorToLabel |
"Put spaces between each word in the selector."
selectorToLabel := [:eachSelector | | label |
label := WriteStream on: (String new: eachSelector size + 10).
"Answer a menu appropriate for the given collection of message selectors and with objectOfVerbs (a String) implied in the menu labels. If objectOfVerbs is nil then the labels will be generated without a objectOfVerbs."
"The objectOfVerbs will be replaced by 'it' in the labels."
"This behavior should exist in PopUpMenu. And PopUpMenu should be generalized since a menu is a more general concept than a PopUpMenu."
| labels lines |
"Convert all the selector predicates into readable predicate phrases."
"Answer a collection of integers representing suggested menu line break points for the given collection of predicate phrases."
"Calculate line breaks between groups of predicate phrases with different verbs (assumed to be first word in predicate phrase) and/or between groups of predicate phrases with different objects of the predicate verb (assumed to be the last word in the predicate phrase). Obviously this isn't optimal but quite workable."